/*
 * MIT License
 *
 * Copyright (c) 2020 wen.gu <454727014@qq.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/***************************************************************************
 * Name: cbus_map.h
 *
 * Purpose: implementation a hash map for cbus endpoint
 *
 * Developer:
 *   wen.gu , 2022-02-16
 *
 * TODO:
 *
 ***************************************************************************/

/******************************************************************************
 **    INCLUDES
 ******************************************************************************/
#ifndef __CBUS_MAP_H__
#define __CBUS_MAP_H__

#include "cbus/core/cbus_type.h"
#include "cbus/core/cbus_error.h"
#include "cbus/core/cbus_macro.h"
/******************************************************************************
 **    MACROS
 ******************************************************************************/
#define CBUS_MAP_DEFAULT_CAPACITY (0)
/******************************************************************************
 **    TYPE DEFINITIONS
 ******************************************************************************/
G_C_HEADER_START

typedef void (*pointer_free_func)(void* ptr);



typedef void (cbus_map_on_for_each_func)(GPTR opaque, GU64 key, GU32 type, const void* value, GU32 value_size);

typedef GBOL (cbus_map_on_for_each_func2)(GPTR opaque, GU64 key, GU32 type, const void* value, GU32 value_size);

/** enum for the data type of value */
typedef enum _cbus_map_value_type
{/** CMV: cbus map value */
	CMV_TYPE_None    = GFCC('n', 'o', 'n', 'e'),
	CMV_TYPE_String  = GFCC('s', 't', 'r', 'i'),
	CMV_TYPE_Int32   = GFCC('i','n','3','2'),
	CMV_TYPE_Int64   = GFCC('i','n','6','4'),
	CMV_TYPE_Float   = GFCC('f','l','o','a'),
	CMV_TYPE_Pointer = GFCC('p','t','r','#'),
	CMV_TYPE_Boolean = GFCC('b', 'o', 'o', 'l'),
	CMV_TYPE_Rect    = GFCC('r', 'e','c','t'),
	CMV_TYPE_Range   = GFCC('r', 'a','n','g'),   
    CMV_TYPE_Struct  = GFCC('s','t','r','u'),
}cbus_map_value_type_t;


struct _cbus_map;
typedef struct _cbus_map* cbus_map_t;
/******************************************************************************
 **    CLASSES/FUNCTIONS DEFINITIONS
 ******************************************************************************/

/**
*@brief  create a map data instance
*
*@param  map [out] return the map data instance 
*
*@return success:G_OK, fail: error code.
*@see
*@note 1. the key type aways GU64
*      2. a map only one value type
*/
G_API cbus_map_t cbus_map_create(GU32 value_type, GU32 default_capacity); /** user set a default size for map item count, if 0,will be use inner default value,maybe 16? */

/**
*@brief  destroy a map data instance
*
*@param  map [in] the map data instance 
*
*@return none.
*@see
*/
G_API void cbus_map_destroy(cbus_map_t map);

/**
*@brief  clear all item in map data
*
*@param  map [in] the map data instance 
*
*@return None.
*@see
*/
G_API void cbus_map_clear(cbus_map_t map);

/**
*@brief  remove a item with the key
*
*@param  map [in] the map data instance
*@param  key  [in] the key of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_remove(cbus_map_t map, GU64 key);



G_API GBOL cbus_map_for_each(cbus_map_t map, cbus_map_on_for_each_func on_for_each, GPTR opaque);

/** if for each loop return GFALSE then will be break the for each and this API will be return GFALSE */
G_API GBOL cbus_map_for_each2(cbus_map_t map, cbus_map_on_for_each_func2 on_for_each, GPTR opaque);

/**
*@brief  set data to map data
*
*@param  map     [in] the map data instance
*@param  key     [in] the key of item
*@param  type    [in] the type of item
*@param  data    [in] data pointer
*@param  size    [in] data size
*@param  on_free [in] a callback to free data(used for pointer type only)
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_data(cbus_map_t map, GU64 key, GU32 type, const void* data, GU32 size, pointer_free_func on_free);

/**
*@brief  find data from map data
*
*@param  map [in]  the map data instance
*@param  key  [in]  the key of item
*@param  type [out] the type of item
*@param  data [out] data pointer
*@param  size [out] data size
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_data(cbus_map_t map, GU64 key, GU32* type, const void** data, GU32* size);
//////////////////////////////////////////////////////////////////////////

/**
*@brief  set a 32 bits integer to map data
*
*@param  map  [in] the map data instance
*@param  key   [in] the key of item
*@param  value [in] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_int32(cbus_map_t map, GU64 key, GS32 value);

/**
*@brief  set a 64 bits integer to map data
*
*@param  map  [in] the map data instance
*@param  key   [in] the key of item
*@param  value [in] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_int64(cbus_map_t map, GU64 key, GS64 value);

/**
*@brief  set a string to map data
*
*@param  map  [in] the map data instance
*@param  key   [in] the key of item
*@param  value [in] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_string(cbus_map_t map, GU64 key, const char* value);

/**
*@brief  set a float to map data
*
*@param  map  [in] the map data instance
*@param  key   [in] the key of item
*@param  value [in] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_float(cbus_map_t map, GU64 key, float value);

/**
*@brief  set a pointer to map data
*
*@param  map  [in] the map data instance
*@param  key   [in] the key of item
*@param  value [in] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_pointer(cbus_map_t map, GU64 key, const void* value,  pointer_free_func on_free);

/**
*@brief  set a boolean to map data
*
*@param  map  [in] the map data instance
*@param  key   [in] the key of item
*@param  value [in] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_boolean(cbus_map_t map, GU64 key, GBOL value);

/**
*@brief  set a rectangle to map data
*
*@param  map  [in] the map data instance
*@param  left  [in] left vertices
*@param  top   [in] top vertices
*@param  right [in] right vertices
*@param bottom [in] bottom vertices
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_rect(cbus_map_t map, GU64 key, GS32 left, GS32 top, GS32 right,GS32 bottom);

/**
*@brief  set a range value to map data
*
*@param  map  [in] the map data instance
*@param  key   [in] the key of item
*@param  start [in] range start
*@param  end   [in] end of range
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_set_range(cbus_map_t map, GU64 key, GS32 start, GS32 end);


G_API GBOL cbus_map_set_struct(cbus_map_t map, GU64 key, const void* struct_addr, GU32 struct_size);

//////////////////////////////////////////////////////////////////////////

/**
*@brief  find a 32 bits integer from map data
*
*@param  map  [in]  the map data instance
*@param  key   [in]  the key of item
*@param  value [out] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_int32(cbus_map_t map, GU64 key, GS32* value);

/**
*@brief  find a 64 bits integer from map data
*
*@param  map  [in]  the map data instance
*@param  key   [in]  the key of item
*@param  value [out] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_int64(cbus_map_t map, GU64 key, GS64* value);

/**
*@brief  find a string from map data
*
*@param  map  [in]  the map data instance
*@param  key   [in]  the key of item
*@param  value [out] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_string(cbus_map_t map, GU64 key, const char** value);

/**
*@brief  find a float from map data
*
*@param  map  [in]  the map data instance
*@param  key   [in]  the key of item
*@param  value [out] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_float(cbus_map_t map, GU64 key, float* value);

/**
*@brief  find a pointer from map data
*
*@param  map  [in]  the map data instance
*@param  key   [in]  the key of item
*@param  value [out] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_pointer(cbus_map_t map, GU64 key, const void** value);

/**
*@brief  find a boolean from map data
*
*@param  map  [in]  the map data instance
*@param  key   [in]  the key of item
*@param  value [out] the value of item
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_boolean(cbus_map_t map, GU64 key, GBOL* value);

/**
*@brief  find a rectangle from map data
*
*@param  map  [in] the map data instance
*@param  key   [in]  the key of item
*@param  left  [out] left vertices
*@param  top   [out] top vertices
*@param  right [out] right vertices
*@param bottom [out] bottom vertices 
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_rect(cbus_map_t map, GU64 key, GS32* left, GS32* top, GS32* right,GS32* bottom);

/**
*@brief  find a range value from map data
*
*@param  map  [in]  the map data instance
*@param  key   [in]  the key of item
*@param  start [out] range start
*@param  end   [out] end of range
*
*@return success: GTRUE, fail:GFALSE.
*@see
*/
G_API GBOL cbus_map_find_range(cbus_map_t map, GU64 key, GS32* start, GS32* end);



G_API GBOL cbus_map_find_struct(cbus_map_t map, GU64 key, void* struct_addr);

G_C_HEADER_END



#endif /** !__CBUS_MAP_H__ */

